package org.stormphoenix.bbsfamily.config

import org.springframework.beans.factory.annotation.Autowired
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder
import org.springframework.security.config.annotation.web.builders.HttpSecurity
import org.springframework.security.config.annotation.web.builders.WebSecurity
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter
import org.springframework.security.crypto.password.PasswordEncoder
import org.springframework.security.web.AuthenticationEntryPoint
import org.springframework.security.web.access.AccessDeniedHandler
import org.springframework.util.DigestUtils
import org.stormphoenix.bbsfamily.controller.CommonResult
import org.stormphoenix.bbsfamily.filter.JwtAuthenticationTokenFilter
import org.stormphoenix.bbsfamily.utils.JsonUtil


@Configuration
@EnableWebSecurity
class WebSecurityConfig : WebSecurityConfigurerAdapter() {

    override fun configure(http: HttpSecurity?) {
        http?.csrf()?.disable()
            ?.authorizeRequests()
            ?.antMatchers("/css/**", "/", "/signin", "/signup")?.permitAll()
            ?.anyRequest()?.authenticated()
            ?.and()
            ?.addFilter(jwtAuthenticationTokenFilter())

        http?.exceptionHandling()
            ?.accessDeniedHandler(accessDeniedHandler())
            ?.authenticationEntryPoint(authenticationEntryPoint())
    }

    override fun configure(web: WebSecurity) {
        // allow Swagger URL to be accessed without authentication
        web.ignoring().antMatchers(
            "/swagger-ui.html",
            "/v2/api-docs", // swagger api json
            "/swagger-resources/configuration/ui", // 用来获取支持的动作
            "/swagger-resources", // 用来获取api-docs的URI
            "/swagger-resources/configuration/security", // 安全选项
            "/swagger-resources/**",
            "/webjars/**"
        )
    }

    @Bean
    fun authenticationEntryPoint(): AuthenticationEntryPoint {
        return AuthenticationEntryPoint { request, httpServletResponse, authException ->
            httpServletResponse.contentType = "application/json;charset=utf-8"
            val out = httpServletResponse.writer
            with(out) {
                write(JsonUtil.objectToJson(CommonResult.unauth()))
                flush()
                close()
            }
        }
    }

    @Bean
    fun accessDeniedHandler(): AccessDeniedHandler {
        return AccessDeniedHandler { httpServletRequest, httpServletResponse, e ->
            httpServletResponse.contentType = "application/json;charset=utf-8"
            val out = httpServletResponse.writer
            with(out) {
                write(JsonUtil.objectToJson(CommonResult.forbidden()))
                flush()
                close()
            }
        }
    }

    @Bean
    fun jwtAuthenticationTokenFilter(): JwtAuthenticationTokenFilter =
        JwtAuthenticationTokenFilter(authenticationManager())


    @Bean
    fun passwordEncoder(): PasswordEncoder =
        object : PasswordEncoder {
            // 此处可以切换加密算法
            override fun encode(charSequence: CharSequence): String {
                return DigestUtils.md5DigestAsHex(charSequence.toString().toByteArray())
            }

            override fun matches(charSequence: CharSequence, s: String): Boolean {
                return s == DigestUtils.md5DigestAsHex(charSequence.toString().toByteArray())
            }
        }

    @Autowired
    fun configureGlobal(auth: AuthenticationManagerBuilder) {
        auth.inMemoryAuthentication().withUser("wangcheng").let {
            it.password("123456")
            it.roles("USER", "ADMIN")
        }
    }
}